package com.crack.nga2.span;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.Volley;
import com.crack.nga2.R;
import com.crack.nga2.activity.NgaApplication;
import com.crack.nga2.utils.GlobalConst;

import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

/**
 * 处理图片标签并载入图片
 * Created by Administrator on 2016/1/11.
 */
public class ImageSpanWrapper {
    public static Drawable defaultDrawable;
    public static Drawable failDrawable;
    private TextView textView;
    private SpannableStringBuilder spannable;
    private static RequestQueue mQueue;
    private BitmapCache bitmapCache;
    private static ImageLoader imageLoader;
    private Object tag;
    private Map<String, ClickableImageSpan> imageSpanMap;
    public static int BITMAP_MAX_WIDTH = 500;
    public static final DiskLruCache diskCache = NgaApplication.diskLruCache;


    public ImageSpanWrapper(TextView textView) {
        this.textView = textView;
        init();
    }

    private void init() {
        spannable = SpannableStringBuilder.valueOf(textView.getText());
        if (mQueue == null) {
            mQueue = NgaApplication.getQueue();
        }
        bitmapCache = BitmapCache.getInstance();
        if (imageLoader == null) {
            imageLoader = NgaApplication.getImageLoader();
        }

        imageSpanMap = new HashMap<>();
        ClickableImageSpan[] imageSpans = spannable.getSpans(0, spannable.length(), ClickableImageSpan.class);
        for (ClickableImageSpan imageSpan : imageSpans) {
            String source = imageSpan.getSource();
            if (source == null) {
                continue;
            }
            int start = spannable.getSpanStart(imageSpan);
            int end = spannable.getSpanEnd(imageSpan);
            imageSpan.start = start;
            imageSpan.end = end;
            imageSpanMap.put(imageSpan.getSource(), imageSpan);
        }
    }

    public void loadImage(int start, int end) {
        tag = textView.getTag(R.id.action_post);
        for (Map.Entry<String, ClickableImageSpan> entry : imageSpanMap.entrySet()) {
            String source = entry.getKey();
            if (source.startsWith("./")) {
                source = GlobalConst.IMG_ATTACH_URL + source.substring(1);
            }
            ClickableImageSpan imageSpan = entry.getValue();
            Drawable drawable = imageSpan.getDrawable();
            if (imageSpan.start <= end || imageSpan.end >= start) {
                if (drawable == defaultDrawable) {
                    Bitmap bitmap = bitmapCache.get(source);
                    if (bitmap != null) {
                        updateImageSpan(bitmap, imageSpan);
                    } else {
                        loadImage(imageSpan, source);
                    }
                }
            }
        }
    }

    private void loadImage(final ClickableImageSpan imageSpan, final String source) {
        if (readFromDiskCache(imageSpan, source)) return;

        Log.i("image", "开始下载" + source);
        imageLoader.get(source, new ImageLoader.ImageListener() {
            @Override
            public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
                Bitmap bitmap = response.getBitmap();
                if (bitmap != null) {
                    Log.i("imageSpan", source + "图片载入完成");
                    writeToDiskCache(bitmap, source);
                    updateImageSpan(bitmap, imageSpan);
                }
            }

            @Override
            public void onErrorResponse(VolleyError error) {
                updateImageSpan(failDrawable, imageSpan);
            }
        }, BITMAP_MAX_WIDTH, BITMAP_MAX_WIDTH);
    }

    /**
     * 从缓存中读取图片
     */
    private boolean readFromDiskCache(ClickableImageSpan imageSpan, String source) {
        try {
            DiskLruCache.Snapshot snapshot = diskCache.get(hashKeyForDisk(source));
            if (snapshot != null) {
                Bitmap bitmap = BitmapFactory.decodeStream(snapshot.getInputStream(0));
                if (bitmap != null) {
                    updateImageSpan(bitmap, imageSpan);
                    Log.i("diskCache", source + "disk缓存读取成功");
                    return true;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private void writeToDiskCache(Bitmap bitmap, String source) {
        try {
            DiskLruCache.Editor edit = diskCache.edit(hashKeyForDisk(source));
            if (edit != null) {
                OutputStream os = edit.newOutputStream(0);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
                Log.i("tag", "存入缓存成功");
                edit.commit();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String hashKeyForDisk(String key) {
        String cacheKey;
        try {
            final MessageDigest mDigest = MessageDigest.getInstance("MD5");
            mDigest.update(key.getBytes());
            cacheKey = bytesToHexString(mDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            cacheKey = String.valueOf(key.hashCode());
        }
        return cacheKey;
    }

    private String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 更新图片
     */
    private void updateImageSpan(Bitmap bitmap, ClickableImageSpan imageSpan) {
        int start = spannable.getSpanStart(imageSpan);
        int end = spannable.getSpanEnd(imageSpan);
        spannable.removeSpan(imageSpan);
        spannable.setSpan(new ClickableImageSpan(getDefaultDrawable(bitmap), "start:" + start) {
            @Override
            public void onClick(View view) {
                Log.i("imageSpan", "点击图片" + view);
                Toast.makeText(view.getContext(), "点击图片", Toast.LENGTH_SHORT).show();
            }
        }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        if (textView.getTag(R.id.action_post) == tag) {
            textView.setText(spannable);
        }
    }

    private void updateImageSpan(Drawable drawable, ClickableImageSpan imageSpan) {
        int start = spannable.getSpanStart(imageSpan);
        int end = spannable.getSpanEnd(imageSpan);
        spannable.setSpan(new ClickableImageSpan(drawable) {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), "点击图片", Toast.LENGTH_SHORT).show();
            }
        }, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        if (textView.getTag(R.id.action_post) == tag) {
            textView.setText(spannable);
        }
    }


    /**
     * 将bitmap转换为Drawable
     */
    private Drawable getDefaultDrawable(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Drawable drawable = new BitmapDrawable(textView.getContext().getResources(), bitmap);
        if (width > 100 || height > 100) {
            float f = width * 1.0f / GlobalConst.SCREEN_WIDTH;
            height = (int) (height / f);
            width = GlobalConst.SCREEN_WIDTH;
        }
        drawable.setBounds(0, 0, width, height);
        return drawable;
    }

    public void releaseBitmap(String source) {

    }
}
